qinglan.Canvas.Animate = qinglan.Canvas.SpriteInterface.extend(function(sprite, map, option) {

	this.sprite = sprite;
	
	this.option = qinglan.Extend.simple({
		delay: 0,
		equal: qinglan.Tween.Quadratic.easeInOut,
		type: 'to',
		duration: 1000
	}, option, 1);

	this.map = map;

	this._data = {};

	this.listener = new qinglan.Listener('_listener' + this.sprite.id,this);
	
	this.__useSelfRender = true; // use self render Function instead of qinglan.Canvas.CanvasRender.drawSprite

	this.init();


}).methods({
	init: function(){
		this._data = qinglan.Canvas.TweenData.createData();

		var data = qinglan.Canvas.Animate.calculate(this.sprite,this.option.type,this.map);

		this._data.sub = data.sub;
		this._data.begin = data.begin;
		this._data.mapLen = data.mapLen;

		this.option.delay > 0 && (this._data.isDelay = true);
	},
	start: function() {
		this._data.isplay = true;
		this._data.startTime = (new Date()).getTime();
		this.listener.notify('start',[this]);
	},
	stop: function() {
		this._data.isplay = false;
		this.listener.notify('stop',[this]);
	},
	push: function(){
		//TODO
		this._data.ispaused = true;
	},
	resume: function(){
		//TODO
		this._data.ispaused = false;
	},
	change: function(ctx){
		qinglan.Canvas.Animate.change(this.sprite, this._data, this.option, this.stop, this);
	},
	update : function(ctx) {
		if (!this._data.isplay) {return false;};
		if (this._data.isDelay){
			var dt = (new Date()).getTime();
			var sub = dt - this._data.startTime;
			if(sub < this.option.delay){
				return false;
			}else{
				this._data.isDelay = false;
				this._data.startTime = (new Date()).getTime();;
				this.change(ctx);
			}	
		}else{ 
			this.change(ctx);
		}
	},
	draw : function(ctx) {
		qinglan.Canvas.CanvasRender.drawSprite(ctx,this.sprite);
	},
	destory: function(){

	}
}).statics({
	calculate: function(sprite, type, map){
		var begin = {};
		var sub = {};
		var mapLen = 0;
		qinglan.Object.each(map,function(val,style){
			if('to' == type){
				begin[style] = sprite.getStyle(style) || 0;
				sub[style] = val - begin[style];
			}else{
				begin[style] = val;
				sub[style] = sprite.getStyle(style) - begin[style];
			}
			mapLen++;
		});
		return {
			sub: sub,
			begin: begin,
			mapLen: mapLen
		}
	},
	change: function(sprite, data, opt, callback, context){
		var t = data.nowTime = (new Date()).getTime() - data.startTime;
		var d  = opt.duration;
		var b = data.begin;
		var c = data.sub;
		if(t>d){ 
			qinglan.Type.isFunction(callback) && callback.call(context); 
			return false;
		}
		qinglan.Object.each(b, function(val,style){
			sprite.setStyle(style, opt.equal(t,val,c[style],d));
		});
		return true;
	}
});
